//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Resource Application Block
//===============================================================================

using System;
using System.Diagnostics.CodeAnalysis;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
using EntLibContrib.Resource.Configuration;
using EntLibContrib.Resource.Instrumentation;

namespace EntLibContrib.Resource
{
	/// <summary>
	/// Static factory class used to get instances of a specified ResourceManager
	/// </summary>
	public static class ResourceFactory
	{
		#region Static Fields
		private static ResourceManagerFactory factory = new ResourceManagerFactory(ConfigurationSourceFactory.Create());
		private static object lockObject = new object();
		#endregion

		#region Public Static Methods
		/// <summary>
		/// Returns the default ResourceManager instance. The same instance should be returned each time this method
		/// is called. The name of the instance to treat as the default ResourceManager is defined in the configuration file.
		/// Guaranteed to return an intialized ResourceManager if no exception is thrown
		/// </summary>
		/// <returns>Default resource manager instance.</returns>
		/// <exception cref="ConfigurationException">Unable to create default ResourceManager</exception>
		public static ResourceManager GetResourceManager()
		{
			try
			{
				lock (lockObject)
				{
					return factory.CreateDefault();
				}
			}
			catch (ConfigurationErrorsException configurationException)
			{
				TryLogConfigurationError(configurationException, "default");
				throw;
			}
		}

		/// <summary>
		/// Gets the resource manager.
		/// </summary>
		/// <param name="resourceManager">The resource manager.</param>
		/// <remarks>This method is used in a resource manager setter and has to use
		/// an output parameter to get around a Windows Forms design issue.</remarks>
		[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters")]
		public static void GetResourceManager(out ResourceManager resourceManager)
		{
			resourceManager = GetResourceManager();
		}

		/// <summary>
		/// Returns the named ResourceManager instance. Guaranteed to return an initialized ResourceManager if no exception is thrown.
		/// </summary>
		/// <param name="resourceManagerName">Name defined in configuration for the resource manager to instantiate</param>
		/// <returns>The requested ResourceManager instance.</returns>
		/// <exception cref="ArgumentNullException">resourceManagerName is null</exception>
		/// <exception cref="ArgumentException">resourceManagerName is empty</exception>
		/// <exception cref="ConfigurationException">Could not find the instance specified by the resourceManagerName</exception>
		/// <exception cref="InvalidOperationException">Error processing configuration information defined in the application configuration file.</exception>
		public static ResourceManager GetResourceManager(string resourceManagerName)
		{
			try
			{
				lock (lockObject)
				{
					return factory.Create(resourceManagerName);
				}
			}
			catch (ConfigurationErrorsException configurationException)
			{
				TryLogConfigurationError(configurationException, resourceManagerName);
				throw;
			}
		}

		/// <summary>
		/// Gets the resource manager.
		/// </summary>
		/// <param name="resourceManagerName">Name defined in configuration for the resource manager to instantiate</param>
		/// <param name="resourceManager">The resulting resource manager.</param>
		/// <remarks>This method is used in a resource manager setter and has to use
		/// an output parameter to get around a Windows Forms design issue.</remarks>
		[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters")]
		public static void GetResourceManager(string resourceManagerName, out ResourceManager resourceManager)
		{
			resourceManager = GetResourceManager(resourceManagerName);
		}

		/// <summary>
		/// Tries to log the configuration error.
		/// </summary>
		/// <param name="configurationException">The configuration exception.</param>
		/// <param name="instanceName">Name of the instance.</param>
		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
		private static void TryLogConfigurationError(ConfigurationErrorsException configurationException, string instanceName)
		{
			try
			{
				DefaultResourceEventLogger eventLogger = EnterpriseLibraryFactory.BuildUp<DefaultResourceEventLogger>();
				if (eventLogger != null)
					eventLogger.LogConfigurationError(instanceName, configurationException);
			}
			catch { }
		}
		#endregion
	}
}